package com.atguigu.srb.core.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * @Description:
 * @Author: Gavin
 * @Date: 7/23/2023 2:12 PM
 */
@Configuration
@Slf4j
public class RabbitmqConfig {
    @Resource
    RabbitTemplate rabbitTemplate;

    @PostConstruct // 构造器调用后立即执行
    //该init方法是用来给rabbitmqTemplate模板类对象设置生产者回调函数用的
    public void init(){
        //确认消息是否到达交换机的回调函数
        //复制小括号,写死右箭头,落实大括号
        //下面的这个方法,不管消息是否到达交换机都会执行
        // rabbitTemplate.setConfirmCallback((@Nullable CorrelationData correlationData, boolean ack, @Nullable String cause)->{
        //也可以直接像下面这样写,可以自己实现类型推断
        rabbitTemplate.setConfirmCallback((correlationData,ack,cause)->{
            if(!ack){
                //进来这里面说明消息没有到达交换机
                log.error("消息没有到达交换机,原因是:{}",cause);
            }
            //否则的话说明消息有到达交换机
            log.info("消息到达交换机了");
        });

        //确认消息是否到达队列的回调函数(只有消息没有到达队列的时候才会执行)
        // rabbitTemplate.setReturnCallback((Message message, int replyCode, String replyText, String exchange, String routingKey)->{
        rabbitTemplate.setReturnCallback((message,replyCode,replyText,exchange,routingKey)->{
            log.error("消息未到达队列,message:{},replyCode:{},exchange:{},routingKey:{}"
                    ,message.toString(),replyCode,exchange,routingKey);
        });
    }
    //初始化业务交换机
    @Bean
    public TopicExchange srbExchange(){
        return ExchangeBuilder.topicExchange("srb.exchange").
                durable(true)//默认是true
                .ignoreDeclarationExceptions()//忽略声明时的异常
                .build();
    }

    //初始化业务队列
    @Bean
    public Queue srbSmsQueue(){
        return QueueBuilder.durable("srb.sms.queue").build();
    }

    @Bean
    //绑定业务交换机和业务队列
    // # 通配任意多级任意多个字符, * 通配一级任意多个字符
    public Binding srbSmsQueueBinding(TopicExchange srbExchange,Queue srbSmsQueue){
        return BindingBuilder.bind(srbSmsQueue).to(srbExchange).with("srb.sms.*");
    }
}
